package org.bingo.service;


import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import org.bingo.dto.UserInfoDto;
import org.bingo.entity.Comment;
import org.bingo.entity.User;
import org.bingo.entity.Video;
import org.bingo.repository.CommentRepository;
import org.bingo.repository.UserRepository;
import org.bingo.repository.VideoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserService {

    @Value("${sa-token.salt}")
    private String salt;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private VideoRepository videoRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private VideoService videoService;

    public Long register(String username,
                            String password,
                            String avatarUrl,
                            String description) {
        if (userRepository.findByUsername(username) != null) {
            return -1L;
        }

        User user = new User();
        user.setUsername(username);
        user.setPassword(SaSecureUtil.md5BySalt(password, salt));
        user.setAvatarUrl(avatarUrl);
        user.setDescription(description);
        userRepository.save(user);
        return user.getId();
    }

    @Transactional
    public UserInfoDto getSelfInfo() {
        User user = userRepository.findById(StpUtil.getLoginIdAsLong()).orElse(null);

        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setId(user.getId());
        userInfoDto.setUsername(user.getUsername());
        userInfoDto.setAvatarUrl(user.getAvatarUrl());
        userInfoDto.setDescription(user.getDescription());
        return userInfoDto;
    }

    public Map<String, Object> login(String username, String password) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            return null;
        }

        if (!user.getPassword().equals(SaSecureUtil.md5BySalt(password, salt))) {
            return null;
        }

        StpUtil.login(user.getId());
        Map<String, Object> loginToken = new HashMap<>();
        loginToken.put(StpUtil.getTokenName(), StpUtil.getTokenValue());
        return loginToken;
    }

    public boolean checkLogin() {
        return StpUtil.isLogin();
    }

    public void logout() {
        if (!checkLogin()) {
            return;
        }

        StpUtil.logout();
    }

    public UserInfoDto info(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            return null;
        }

        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setId(user.getId());
        userInfoDto.setUsername(user.getUsername());
        userInfoDto.setAvatarUrl(user.getAvatarUrl());
        userInfoDto.setDescription(user.getDescription());
        return userInfoDto;
    }

    public UserInfoDto info(Long id) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            return null;
        }

        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setId(user.getId());
        userInfoDto.setUsername(user.getUsername());
        userInfoDto.setAvatarUrl(user.getAvatarUrl());
        userInfoDto.setDescription(user.getDescription());
        return userInfoDto;
    }

    @Transactional
    public Long logoff() {
        if (!checkLogin()) {
            return -1L;
        }

        Long id = StpUtil.getLoginIdAsLong();
        if (id == null) {
            return -1L;
        }
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            return -1L;
        }

        List<Comment> comments = commentRepository.findByUser(user);
        commentRepository.deleteAll(comments);
        List<Video> videos = videoRepository.findByUser(user);
        videos.forEach(video -> {
            userRepository.dropLikeRelation(video.getId());
            userRepository.dropCollectRelation(video.getId());
            videoService.delVideo(video.getId());
        });
        logout();
        userRepository.delete(user);
        return id;
    }

    @Transactional
    public UserInfoDto updateUser(String username,
                           String password,
                           String avatarUrl,
                           String description) {
        User user = userRepository.findById(StpUtil.getLoginIdAsLong()).orElse(null);
        user.setUsername(username);
        if (password != null && !password.equals("")) {
            user.setPassword(SaSecureUtil.md5BySalt(password, salt));
        }
        user.setAvatarUrl(avatarUrl);
        user.setDescription(description);
        userRepository.save(user);
        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setId(user.getId());
        userInfoDto.setUsername(user.getUsername());
        userInfoDto.setAvatarUrl(user.getAvatarUrl());
        userInfoDto.setDescription(user.getDescription());
        return userInfoDto;
    }

    @Transactional
    public List<Video> getVideosByUserId(Long userId) {
        User user = userRepository.findById(userId).orElse(null);
        if (user == null) {
            return null;
        }

        return videoRepository.findByUser(user);
    }

    @Transactional
    public List<Video> getLikedVideo() {
        User user = userRepository.findById(StpUtil.getLoginIdAsLong()).orElse(null);
        return user.getLikeVideos();
//        return videoRepository.findByLikedUser(user);
    }

    @Transactional
    public List<Video> getCollectedVideo() {
        User user = userRepository.findById(StpUtil.getLoginIdAsLong()).orElse(null);
        return user.getCollectVideos();
//        return videoRepository.findByCollectedUser(user);
    }

}
